package mspbots.timedoctor.client.core.api.v2;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.log4j.Log4j2;
import mspbots.timedoctor.client.config.RabbitConfiguration;
import mspbots.timedoctor.client.core.api.BaseApiService;
import mspbots.timedoctor.client.core.api.ResultMessageModel;
import mspbots.timedoctor.client.core.api.constant.API;
import mspbots.timedoctor.client.core.listener.SyncTimeDTO;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * data.connector.timedoctor.api.PayrollsService
 *
 * @author Jay.Yang
 * @date Created by 2020/3/26
 */
@Log4j2
@Service
public class WorkLogsV2Service extends BaseApiService {
    private static Map api_status = new ConcurrentHashMap();
    private final String WORKLOGS_REDIS_KEY = "sync-activity-worklog-";

    public void async(String sync_id, Long tenant, String companyId, JsonNode userNode) {
        if (ObjectUtils.isEmpty(userNode)) {
            log.error("time doctor sync worklogs over!,user is null.");
            return;
        }
        LocalDateTime paramTo = LocalDateTime.now();
        Iterator<JsonNode> entity = userNode.elements();
        while (entity.hasNext()) {
            final long start = System.nanoTime();
            String userId = entity.next().get("id").asText();
            super.loadRedisValue(this.WORKLOGS_REDIS_KEY + tenant + ":" + userId).flatMapMany(from ->
                    this.doctorV2Client.get(API.V2_WORKLOG, Map.of("tenantId", tenant, "company", companyId,
                            "from", from, "to", paramTo, "user", userId))
                            .map(jsonNode -> jsonNode.get("data")))
                    .subscribe(result -> {
                                if (!ObjectUtils.isEmpty(result) && !"[[]]".equals(result.toString())) {
                                    this.messagingTemplate.convertAndSend(RabbitConfiguration.DATA_CONNECTOR_TIMEDOCTOR,
                                            "timedoctor-worklogs-key",
                                            ResultMessageModel.builder().action(ResultMessageModel.MessageModelAction.ADD)
                                                    .type(ResultMessageModel.MessageModelType.WORKLOGS)
                                                    .sendTime(LocalDateTime.now())
                                                    .entity(result)
                                                    .tenantId(tenant)
                                                    .build());
                                    setEndStartTime(this.WORKLOGS_REDIS_KEY + tenant + ":" + userId, result);
                                }

                                long milliseconds = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
                                log.debug("Time taken {}: {}  milliseconds.", "Completed", TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start));
                                this.messagingTemplate.convertAndSend("timedoctor.sync.time", SyncTimeDTO.builder()
                                        .api(API.V2_WORKLOG)
                                        .last_time(LocalDateTime.now())
                                        .milliseconds(milliseconds)
                                        .status("Completed")
                                        .msg("Success")
                                        .tenantId(tenant)
                                        .build()
                                );


                                this.sendLog(sync_id, tenant, milliseconds, API.V2_WORKLOG, SUCCESS_CODE, "", result);
                            }
                            , err -> {
                                log.error("Companies sync data error, msg:{}", err.getMessage());
                                long milliseconds = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
                                this.messagingTemplate.convertAndSend("timedoctor.sync.time", SyncTimeDTO.builder()
                                        .api(API.V2_WORKLOG)
                                        .last_time(LocalDateTime.now())
                                        .milliseconds(milliseconds)
                                        .status("Error")
                                        .msg(err.getMessage())
                                        .tenantId(tenant)
                                        .build()
                                );


                                this.sendLog(sync_id, tenant, milliseconds, API.V2_WORKLOG, FAIL_CODE, err.getMessage(), null);
                            }
                    );
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void setEndStartTime(String key, JsonNode result) {
        Iterator<JsonNode> nodes = result.get(0).elements();
        LocalDateTime startTime = null;
        while (nodes.hasNext()) {
            JsonNode node = nodes.next();
            LocalDateTime start = LocalDateTime.parse(node.findValue("start").asText(), DateTimeFormatter.ISO_DATE_TIME);
            if (ObjectUtils.isEmpty(startTime) || startTime.isBefore(start)) {
                startTime = start;
            }
        }
        if (!ObjectUtils.isEmpty(startTime)) {
            super.recordRedisValue(key, startTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        }
    }
}
